package com.stars.easyms.mq.interceptor;

import com.stars.easyms.base.util.SpringBootUtil;
import com.stars.easyms.base.util.ThreadUtil;
import com.stars.easyms.mq.annotation.MQSender;
import com.stars.easyms.mq.constant.MQConstants;
import com.stars.easyms.mq.core.EasyMsMQSender;
import com.stars.easyms.mq.exception.EasyMsMQException;
import com.stars.easyms.mq.initializer.MQManagerInitializer;
import com.stars.easyms.mq.properties.EasyMsMQProperties;
import com.stars.easyms.mq.util.EasyMsMQUtil;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Method;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * <p>className: MQSenderInterceptor</p>
 * <p>description: MQSender拦截器</p>
 *
 * @author guoguifang
 * @version 1.2.1
 * @date 2019-03-20 10:29
 */
public class MQSenderInterceptor implements MethodInterceptor {

    private EasyMsMQSender easyMsMQSender;

    private EasyMsMQProperties easyMsMQProperties;

    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        // 获取当前方法与方法名
        Method method = methodInvocation.getMethod();

        // 判断是否有MQSender注解
        if (!method.isAnnotationPresent(MQSender.class)) {
            return methodInvocation.proceed();
        }

        // 检查mq是否初始化完成，如果未完成则延迟15秒
        checkMqInitStatus(MQConstants.MQ_INIT_ING_DELAY_SECONDS);

        // 获取MQSender注解、当前方法名称、类对象及类名称
        MQSender mqSender = method.getAnnotation(MQSender.class);
        String pointMethodName = method.getName();
        Class<?> mqManagerClass = method.getDeclaringClass();
        String mqManagerClassName = mqManagerClass.getName();

        // 根据注解类型获取key
        String key = mqSender.key();
        boolean isElExpression = key.startsWith("${") && key.endsWith("}") || key.contains(".");
        if (isElExpression) {
            key = easyMsMQProperties.getKey().get(EasyMsMQUtil.getReplaceKey(key));
            if (StringUtils.isBlank(key)) {
                throw new EasyMsMQException("MQ manager ({}) method({}) annotation(MQSender) key '{}' didn't find in config!", mqManagerClassName, pointMethodName, key);
            }
        }

        if (mqSender.isDynamicKey()) {
            try {
                key = StringUtils.join(new Object[]{key, SpringBootUtil.getActiveProfile()}, "_");
            } catch (Exception e) {
                throw new EasyMsMQException("MQ manager({}) method({}) annotation(MQSender) use dynamic key, {}!", mqManagerClassName, pointMethodName, e.getMessage());
            }
        }

        // 如果是多通道发送则获取随机的通道
        int channelCount = mqSender.channelCount();
        if (channelCount > 1) {
            key = StringUtils.join(new Object[]{key, StringUtils.leftPad(String.valueOf(new Random().nextInt(channelCount > 5 ? 5 : channelCount) + 1), 3, "0")}, "-");
        }

        // 获取方法的输入参数并发送消息
        easyMsMQSender.send(key, mqSender.destinationType(), mqSender.redeliveryPolicy(), mqSender.redeliveryDelay(), methodInvocation.getArguments()[0]);
        return null;
    }

    private void checkMqInitStatus(int delaySeconds) {
        if (MQManagerInitializer.getInitStatus() == MQConstants.MQ_INIT_STATUS_SUCCESS) {
            return;
        }
        if (MQManagerInitializer.getInitStatus() == MQConstants.MQ_INIT_STATUS_FAIL) {
            throw new EasyMsMQException("MQ init fail, cant't send message!");
        }
        if (delaySeconds <= 0) {
            throw new EasyMsMQException("MQ init timeout, cant't send message!");
        }
        ThreadUtil.sleep(1, TimeUnit.SECONDS);
        checkMqInitStatus(--delaySeconds);
    }

    public MQSenderInterceptor(EasyMsMQSender easyMsMQSender, EasyMsMQProperties easyMsMQProperties) {
        this.easyMsMQSender = easyMsMQSender;
        this.easyMsMQProperties = easyMsMQProperties;
    }

}